package com.lmt.ymcc.service.impl;

import com.lmt.ymcc.constant.SmsConstant;
import com.lmt.ymcc.dto.RedisTempDto;
import com.lmt.ymcc.dto.VerifyCodeDto;
import com.lmt.ymcc.exception.GlobalException;
import com.lmt.ymcc.result.JSONResult;
import com.lmt.ymcc.service.IVerifyCodeService;
import com.lmt.ymcc.utils.AssertUtil;
import com.lmt.ymcc.utils.StrUtils;
import com.lmt.ymcc.utils.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;


/**
 * @Description: 发送验证码业务逻辑类
 * @Author: Amazing
 * @Date: 2022/8/6 12:50
 * @Version: 1.0
 */
@Service
@Slf4j
public class IVerifyCodeServiceImpl implements IVerifyCodeService {


    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Override
    public JSONResult sendSmsCode(VerifyCodeDto verifyCodeDto) {
        // 判断图形验证码是否正确
        String imgCodeKey = (String)redisTemplate.opsForValue().get(SmsConstant.IMG_CODE_KEY);
        boolean checkImgCode = imgCodeIsTrue(imgCodeKey, verifyCodeDto.getImageCode());
        AssertUtil.isTrue(checkImgCode, "图形验证码错误");
        // 判断是否已经存在手机验证码
        RedisTempDto redisTempDto = (RedisTempDto)redisTemplate.opsForValue().get(SmsConstant.SMS_CODE_KEY + verifyCodeDto.getImageCodeKey());
        String SmsCodeKey = SmsConstant.SMS_CODE_KEY + verifyCodeDto.getMobile();
        String SmsCodeValue = null;
        if (redisTempDto == null) {
            // 生成新的验证码
            SmsCodeValue = StrUtils.getComplexRandomString(6);
            redisTemplate.opsForValue().set(SmsCodeKey, SmsCodeValue, 3, TimeUnit.MINUTES);
            redisTempDto = new RedisTempDto(SmsCodeKey ,SmsCodeValue,new Date());
            // 调用发送验证码的工具类，发送验证码
            log.info("================================");
            log.info("您的验证码是：\n" + SmsCodeValue);
            log.info("================================");
        }else {
            // 判断两次获取验证码的时间间隔是否在1分钟内
            Date createTime = redisTempDto.getCreateTime();
            if ((System.currentTimeMillis()-createTime.getTime())/1000 > 60) {
                // 如果在，提示用户1分钟之后再获取
                throw new GlobalException("获取验证码间隔太短，请稍后重试");
            }else {
                // 如果不在，调用发送验证码的工具类，发送验证码
                SmsCodeValue = StrUtils.getComplexRandomString(6);
                redisTemplate.opsForValue().set(SmsCodeKey, SmsCodeValue, 3, TimeUnit.MINUTES);
                redisTempDto = new RedisTempDto(SmsCodeKey ,SmsCodeValue,new Date());
                log.info("===========================");
                log.info("您的验证码是：\n" + SmsCodeValue);
                log.info("===========================");
            }

        }
        return JSONResult.success();
    }

    /**
    * @Title: imageCode
    * @Description: 获取图形验证码
    * @Author: Amazing
    * @Version: 1.0
    * @Date:  2022/8/6 17:52
    * @Parameters: [imgCode]
    * @Return com.lmt.ymcc.result.JSONResult
     * 3fd4d15e-9b86-4e0b-aab0-cc11a20ca9db
    */
    @Override
    public JSONResult imageCode(String imageCodeKey) {
        // 发送图形验证码
        if (StringUtils.isEmpty(imageCodeKey)) {
            throw new GlobalException("系统异常，参数不正确");
        }
        // 获取四位随机数
        String code = StrUtils.getComplexRandomString(4);
        // 获取添加到Redis中
        redisTemplate.opsForValue().set(imageCodeKey, code, 5, TimeUnit.MINUTES);
        redisTemplate.opsForValue().set(SmsConstant.IMG_CODE_KEY, imageCodeKey);
        // 获取并返回base64字符串
        String base64Code = VerifyCodeUtils.verifyCode(100, 30, code);
        return JSONResult.success(base64Code);
    }

    /**
    * @Title: imgCodeIsTrue
    * @Description: 判断图形验证码是否正确
    * @Author: Amazing
    * @Version: 1.0
    * @Date:  2022/8/6 17:52
    * @Parameters: [imgCodeKey, imageCode]
    * @Return boolean
    */
    private boolean imgCodeIsTrue(String imgCodeKey, String imageCode) {
        // 从redis中获取图形验证码并判断是否正确
        String redisImgCode = (String)redisTemplate.opsForValue().get(imgCodeKey);
        if (StringUtils.equalsIgnoreCase(redisImgCode, imageCode)){
            return true;
        }
        return false;
    }
}
